﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
using Validation.sp2010.Classes;
using System.Collections.Generic;
using Validation.sp2010.Helper;
using System.Globalization;
using Microsoft.SharePoint.Utilities;
using System.Collections.Specialized;
using System.Net;
using System.Net.Mail;

namespace Validation.sp2010.WorkFlow.ValidationWorkflow
{
    public sealed partial class ValidationWorkflow : SequentialWorkflowActivity
    {
        public ValidationWorkflow()
        {
            InitializeComponent();
        }
        #region messages

        string label_step_task;
        string label_step_mail;
        string label_step_extension;
        string msg_mail;
        string msg_validate;
        string msg_refuse;
        string msg_extension;
        string msg_loging_format;
        string msg_no_comment;
        string msg_hsitoric_item_format;
        #endregion

        #region Properties
        List<StepWF> steps;
        ValidationWorkflowAssociation parametres;
        bool workFlowTerminated = false;
        bool useStep = true;
        int currentStep = 0;
        string nextValidator;
        string taskCompletedValue;
        bool approuved = true;

        string commentHistoricItem = string.Empty;
        string actorHistoricitem = string.Empty;
        string logError = "";
        #endregion
        public Guid workflowId = default(System.Guid);
        public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();

        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
        {
            Log.Entry();

            #region Set messages

            SPWeb web = workflowProperties.Web;
            label_step_task = HelperUtilities.GetResources("label_step_task", web.Language);
            label_step_mail = HelperUtilities.GetResources("label_step_mail", web.Language);
            label_step_extension = HelperUtilities.GetResources("label_step_extension", web.Language);
            msg_mail = HelperUtilities.GetResources("msg_mail", web.Language);
            msg_validate = HelperUtilities.GetResources("msg_validate", web.Language);
            msg_refuse = HelperUtilities.GetResources("msg_refuse", web.Language);
            msg_extension = HelperUtilities.GetResources("msg_extension", web.Language);
            msg_loging_format = HelperUtilities.GetResources("msg_loging_format", web.Language);
            msg_no_comment = HelperUtilities.GetResources("msg_no_comment", web.Language);
            msg_hsitoric_item_format = HelperUtilities.GetResources("msg_hsitoric_item_format", web.Language);
            taskCompletedValue = SPResource.GetString(CultureInfo.GetCultureInfo((int)workflowProperties.Web.Language), "WorkflowTaskStatusComplete");

            #endregion

            parametres = Helper.HelperSerializer.XmlDeserializeFromString(workflowProperties.AssociationData, typeof(ValidationWorkflowAssociation)) as ValidationWorkflowAssociation;
            steps = parametres.Steps;
            currentStep = steps.FirstOrDefault(s => s.IsInitial).Sequence;
            //set item state to in progress
            try
            {
                SPList list = workflowProperties.List;
                SPListItem item = workflowProperties.Item;
                item[new Guid(parametres.StateFieldId)] = (list.Fields[new Guid(parametres.StateFieldId)] as SPFieldChoice).Choices[1];
                item.Update();
            }
            catch (Exception ex)
            {
                logError += "onWorkflowActivated1_Invoked :" + ex.Message;

                Log.Error(ex.Message);
            }

        }

        #region While boucle
        private void TerminateStepsCondition(object sender, ConditionalEventArgs e)
        {
            e.Result = !workFlowTerminated;
        }

        #region ifElseTask
        private void IsTaskCondition(object sender, ConditionalEventArgs e)
        {
            //we use extension task or our step is  task validation
            e.Result = !useStep || (this.steps.FirstOrDefault(s=>s.Sequence==currentStep).TypeStep == TypeStep.Task);
        }

        #region Create Task
        public Guid CreateTask_TaskId = default(System.Guid);
        public SPWorkflowTaskProperties CreateTask_TaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public String CreateTask_ContentTypeId = default(System.String);

        private void CreateTask_MethodInvoking(object sender, EventArgs e)
        {
            Log.Entry();
            try
            {
                CreateTask_TaskId = Guid.NewGuid();
                CreateTask_ContentTypeId = Constante.ct_Task_Validation;
                taskTerminated = false;

                StepWF step = steps.FirstOrDefault(s => s.Sequence == currentStep);
                CreateTask_TaskProperties.Title = HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Object);
                CreateTask_TaskProperties.Description = HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Body);


                if (useStep)
                {

                    List<SPPrincipal> usersActor = step.Actor.GetPrincipal(workflowProperties.Web, workflowProperties.List, workflowProperties.Item);

                    if (usersActor.Count > 0 && usersActor[0] != null)
                        CreateTask_TaskProperties.AssignedTo = usersActor[0].LoginName; //fieldUsers.ToString();
                    else
                        CreateTask_TaskProperties.AssignedTo = step.Actor.SecondaryValidator;

                    CreateTask_TaskProperties.ExtendedProperties[Constante.FieldGuid.WithExtention] = step.WithExtension;

                }
                else
                {
                    CreateTask_TaskProperties.AssignedTo = nextValidator;
                    CreateTask_TaskProperties.ExtendedProperties[Constante.FieldGuid.WithExtention] = step.ProlongedExtension;

                    useStep = true;
                }
                CreateTask_TaskProperties.ExtendedProperties[Constante.FieldGuid.ForceValidation] = step.ForceValidation;
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }

        public SPWorkflowTaskProperties onTaskChanged_AfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChanged_BeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();


        private void onTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
        {

            Log.Entry();
            try
            {

                if (onTaskChanged_AfterProperties.ExtendedProperties[SPBuiltInFieldId.TaskStatus] == null ||
                    onTaskChanged_AfterProperties.ExtendedProperties[SPBuiltInFieldId.TaskStatus].ToString() != taskCompletedValue)
                    return;

                taskTerminated = true;

                SPListItem item = workflowProperties.Item;
                SPList list = workflowProperties.List;
                StepWF step = steps.FirstOrDefault(s => s.Sequence == currentStep);

                SPListItem currentTask = workflowProperties.TaskList.GetItemById(onTaskChanged_AfterProperties.TaskItemId);
                actorHistoricitem = HelperUtilities.GetValueLookup(currentTask[SPBuiltInFieldId.Editor].ToString());
                commentHistoricItem = currentTask[Constante.FieldGuid.Comment] != null ? currentTask[Constante.FieldGuid.Comment].ToString() : string.Empty;
                if (string.IsNullOrEmpty(commentHistoricItem))
                    commentHistoricItem = msg_no_comment;


                ///Get response
                string _extResponse = (workflowProperties.TaskList.Fields[Constante.FieldGuid.Response] as SPFieldChoice).Choices[0];
                string _validatResponse = (workflowProperties.TaskList.Fields[Constante.FieldGuid.Response] as SPFieldChoice).Choices[1];
                string _refuseResponse = (workflowProperties.TaskList.Fields[Constante.FieldGuid.Response] as SPFieldChoice).Choices[2];

                string response = onTaskChanged_AfterProperties.ExtendedProperties[Constante.FieldGuid.Response].ToString();

                #region Extension
                if (response == _extResponse)
                {
                    useStep = false;
                    SPPrincipal nextValidatorUser;

                    try
                    {
                        nextValidatorUser = workflowProperties.Web.AllUsers[onTaskChanged_AfterProperties.ExtendedProperties[Constante.FieldGuid.NextValidator].ToString()];

                    }
                    catch (Exception)
                    {

                        nextValidatorUser = workflowProperties.Web.SiteGroups[onTaskChanged_AfterProperties.ExtendedProperties[Constante.FieldGuid.NextValidator].ToString()];

                    }
                    nextValidator = nextValidatorUser.LoginName;

                    //Notification
                    logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_task, step.Title);
                    logToHistory_HistoryOutcome = string.Format(msg_extension, actorHistoricitem, nextValidatorUser.Name, commentHistoricItem);
                }


                #endregion

                #region refuse
                if (response == _refuseResponse)
                {
                    //workFlowTerminated = true;
                    approuved = false;
                    if (step.IsFinal || step.NextStepRefuse==0)
                    {
                        workFlowTerminated = true;
                    }
                    else
                    {
                        currentStep = step.NextStepRefuse;
                    }

                    //Notification
                    logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_task, step.Title);
                    logToHistory_HistoryOutcome = string.Format(msg_refuse, actorHistoricitem, commentHistoricItem);
                }
                #endregion

                #region Validated
                if (response == _validatResponse)
                {
                    if (step.IsFinal || step.NextStepValidation==0)
                    {
                        workFlowTerminated = true;
                    }
                    else
                    {
                        currentStep = step.NextStepValidation;
                    }




                    //Notification
                    logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_task, step.Title);
                    logToHistory_HistoryOutcome = string.Format(msg_validate, actorHistoricitem, commentHistoricItem);

                }
                #endregion


            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }

        }
        bool taskTerminated = false;
        private void TaskTerminatedCondition(object sender, ConditionalEventArgs e)
        {
            e.Result = !taskTerminated;
        }
        #endregion

        #region Update historic Item
        private void UpdateItemistorie_ExecuteCode(object sender, EventArgs e)
        {
            Log.Entry();
            //set historic item
            try
            {
                SPListItem item = workflowProperties.Item;
                item[new Guid(parametres.HistoriqueFieldId)] += string.Format(msg_hsitoric_item_format, actorHistoricitem, commentHistoricItem);
                item.Update();
            }
            catch (Exception ex)
            {
                logError += "UpdateItemistorie_ExecuteCode :" + ex.Message+"\n\t";
                Log.Error(ex);
            }
        }
        #endregion






        #region SendMail

        public String SendEmail_Body = default(System.String);
        public String SendEmail_From = default(System.String);
        public StringDictionary SendEmail_Headers = new StringDictionary();
        public String SendEmail_Subject = default(System.String);
        public String SendEmail_To = default(System.String);
        public String SendEmail_CC = default(System.String);

        private void SendMailActivity_ExecuteCode(object sender, EventArgs e)
        {
            Log.Entry();
            try
            {
                StepWF step = steps.FirstOrDefault(s => s.Sequence == currentStep);
                List<SPPrincipal> usersActor = step.Actor.GetPrincipal(workflowProperties.Web, workflowProperties.List, workflowProperties.Item);

                StringDictionary headers = new StringDictionary();

                string toMail = "";
                usersActor.ForEach(p =>
                {
                    SPUser u = workflowProperties.Web.EnsureUser(p.LoginName);
                    if (!string.IsNullOrEmpty(u.Email))
                        toMail += u.Email + ";";
                });
                if (toMail.Length > 1)
                    toMail = toMail.Remove(toMail.Length - 1);

                string ccMail = "";
                if (step.CC_Mail != null)
                {

                    List<SPPrincipal> usersCCMail = step.CC_Mail.GetPrincipal(workflowProperties.Web, workflowProperties.List, workflowProperties.Item);
                    usersCCMail.ForEach(p =>
                    {
                        SPUser u = workflowProperties.Web.EnsureUser(p.LoginName);
                        if (!string.IsNullOrEmpty(u.Email))
                            ccMail += u.Email + ";";
                    });

                    if (ccMail.Length > 1)
                        ccMail = ccMail.Remove(ccMail.Length - 1);

                }

                try
                {
                    sendMail(toMail, ccMail,
                           HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Object),
                           HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Body));


                }
                catch (Exception ex)
                {
                    logError += "SendMailActivity_ExecuteCode :" + ex.Message + "\n\t";
                }

                if (step.IsFinal)
                {
                    workFlowTerminated = true;
                }
                else
                {
                    currentStep = step.NextStepValidation;
                }

                //Notification
                logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_mail, step.Title);
                logToHistory_HistoryOutcome = string.Format(msg_mail, string.IsNullOrEmpty(toMail) ? "-" : toMail,
                    string.IsNullOrEmpty(ccMail) ? "-" : ccMail);


            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }
        private void sendMail(string to, string cc, string objectMail, string bodyMail)
        {
            if (!string.IsNullOrEmpty(to))
            {
                try
                {
                    StringDictionary headers = new StringDictionary();
                    headers.Add("to", to);

                    if (!string.IsNullOrEmpty(cc))
                        headers.Add("cc", cc);

                    headers.Add("bcc", "");
                    headers.Add("from", "");
                    headers.Add("subject", objectMail);
                    headers.Add("content-type", "text/html");
                    SPUtility.SendEmail(workflowProperties.Web, headers, bodyMail);
                }
                catch (Exception ex)
                {
                    Log.Error(ex);
                }

                
            }

     
        }
        #endregion



        #endregion

        #region Log To Historie

        public String logToHistory_HistoryDescription = default(System.String);
        public String logToHistory_HistoryOutcome = default(System.String);
        private void logToHistory_MethodInvoking(object sender, EventArgs e)
        {

        }

        #endregion





        #endregion

        #region Change state

        private void ChangeState_ExecuteCode(object sender, EventArgs e)
        {
            //set historic item
            Log.Entry();
            try
            {
                SPList list = workflowProperties.List;
                SPListItem item = workflowProperties.Item;
                item[new Guid(parametres.StateFieldId)] = approuved ? (list.Fields[new Guid(parametres.StateFieldId)] as SPFieldChoice).Choices[2] : (list.Fields[new Guid(parametres.StateFieldId)] as SPFieldChoice).Choices[3];
                item.Update();
            }
            catch (Exception ex)
            {
                logError += "UpdateItemistorie_ExecuteCode :" + ex.Message;
                Log.Error(ex);
            }
        }
        #endregion











    }
}
